#include "HttpServer.h"
#include "Connection.h"

#include <iostream>
#include <boost/lexical_cast.hpp>
#include <boost/foreach.hpp>
#include <boost/bind.hpp>

namespace HTTP_SERVER {
    
    HttpServer::HttpServer(int port) : serverPort_(port), ioService_(), serverSocket_(ioService_), acceptor_(ioService_) {
        
        boost::asio::ip::tcp::resolver resolver(ioService_);
        boost::asio::ip::tcp::resolver::query query("localhost", boost::lexical_cast<std::string>(serverPort_));
        boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query);
        boost::asio::ip::tcp::resolver::iterator end; // End marker.
        while (iter != end)
        {
            serverEndPoints_.push_back(*iter++);
        }
        
    }

    
    void HttpServer::start() {
        
        bool connectionStatus = false ;
        BOOST_FOREACH(boost::asio::ip::tcp::endpoint endPoint , serverEndPoints_ ){
            try{
                acceptor_.open(endPoint.protocol());
                acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
                acceptor_.bind(endPoint);
                acceptor_.listen();
                connectionStatus = true ;
                break ;
            }catch(const boost::system::system_error& error){
                std::cout <<  " Exception while initializing acceptor for endpoint: " << endPoint << " :: " << error.what() << std::endl ;
            }
        }
        if(connectionStatus){
            std::cout << " Connection Successful. " << std::endl ;
        }else{
            std::cout << " Can not Connect. " << std::endl ;
        }
        
        // Start Accepting Connection
        acceptor_.async_accept(serverSocket_, boost::bind(&HttpServer::doAccept, this, _1));
        
        ioService_.run();
        
    }
    
    void HttpServer::doAccept(boost::system::error_code ec){
        
        if(!acceptor_.is_open()){
            std::cout << " Acceptor is not open to accept new connection. " << std::endl ;
            return ;
        }
        
        if(!ec){
            
            std::cout << " Connection accepted. " << std::endl ;
            // Handle the incoming connection
            Connection conn(std::move(serverSocket_));
            conn.start();
        }else{
            std::cout << " Problem while accepting connection :: " << ec.message() << std::endl ;
        }
        acceptor_.async_accept(serverSocket_, boost::bind(&HttpServer::doAccept, this, _1));
    }
    
};
